/** @file

Copyright (c) 2006-2023, Kunlun BIOS, Kunlun Technology (Beijing) Co., Ltd.. All
Rights Reserved.

You may not reproduce, distribute, publish, display, perform, modify, adapt,
transmit, broadcast, present, recite, release, license or otherwise exploit
any part of this publication in any form, by any means, without the prior
written permission of Kunlun Technology (Beijing) Co., Ltd..

Module Name:


Abstract:


Revision History:

**/

#include "SetupConfig.h"
#include <OEMSvc.h>
#include <Advance.h>
#include <Guid/MdeModuleHii.h>
#include <Protocol/HiiString.h>

extern EFI_SMBIOS_HANDLE               gSmbiosHandle;
extern EFI_SMBIOS_TYPE                 gSmbiosType;

extern EFI_HII_HANDLE           gAdvHiiHandle;
extern EFI_SMBIOS_PROTOCOL      *gSmbiosProtocol;


/**

  Update CPU information on the main page.

**/
VOID
UpdateCpuInformation (VOID)
{
  EFI_STATUS                  Status;
  SMBIOS_TABLE_TYPE4          *SmbiosType4Record;
  SMBIOS_TABLE_TYPE7          *SmbiosType7Record;
  EFI_SMBIOS_TABLE_HEADER     *SmbiosRecord;
  CHAR8                       *TempString;
  UINT32                      CpuNum;
  UINT8                       CacheLevel;
  UINT32                      CacheSize;
  UINT8                       CacheSizeGranularity;
//add-klk-lyang-P000A-start//
  CHAR16                      CacheSizeUnit[3][5] = {L"KB",L"MB",L"GB"};
  UINTN                       UintIndex;
//add-klk-lyang-P000A-end//
  //
  // Update processor information via smbios.
  //
  if (NULL == gSmbiosProtocol) {
    goto EndGetSmbiosInfo;
  }

  CpuNum = 0;
  gSmbiosHandle = (gSmbiosType < EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION) ? gSmbiosHandle : SMBIOS_HANDLE_PI_RESERVED;
  gSmbiosType = EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION;

  Status = gSmbiosProtocol->GetNext (gSmbiosProtocol, &gSmbiosHandle, &gSmbiosType, &SmbiosRecord, NULL);
  if (EFI_ERROR(Status)) {
    DEBUG((EFI_D_ERROR, "UpdateCpuInformation SmbiosProtocol GetNext fail Status=%r\n", Status));
    goto EndGetSmbiosInfo;
  }

  SmbiosType4Record = (SMBIOS_TABLE_TYPE4 *) SmbiosRecord;
  CpuNum++;
  //
  // Update PROCESSOR_VENDOR
  //
  TempString = KlGetSmbiosString (SmbiosRecord, SmbiosType4Record->ProcessorManufacturer);
  InitString (gAdvHiiHandle, STRING_TOKEN (STR_BOARD_PROCESSOR_VENDOR_VALUE), L"%a", TempString);

  //
  // Update PROCESSOR_NAME
  //
  TempString = KlGetSmbiosString (SmbiosRecord, SmbiosType4Record->ProcessorVersion);
  InitString (gAdvHiiHandle, STRING_TOKEN (STR_BOARD_PROCESSOR_VALUE), L"%a", TempString);

  //
  // Update PROCESSOR_SPEED
  //
  InitString (gAdvHiiHandle, STRING_TOKEN (STR_BOARD_PROCESSOR_SPEED_VALUE), L"%d MHz", SmbiosType4Record->CurrentSpeed);

  //
  // Update PROCESSOR_PRID
  //
  InitString (gAdvHiiHandle, STRING_TOKEN (STR_BOARD_PROCESSOR_PRID_VALUE), L"%08lx", (*(UINT64 *) (&SmbiosType4Record->ProcessorId)));

  while (1) {
    Status = gSmbiosProtocol->GetNext (gSmbiosProtocol, &gSmbiosHandle, &gSmbiosType, &SmbiosRecord, NULL);
    if (EFI_ERROR(Status)) {
      break;
    }

    CpuNum++;
  }

  //
  // Update PROCESSOR_COUNT
  //
  InitString (gAdvHiiHandle, STRING_TOKEN (STR_BOARD_PROCESSOR_COUNT_VALUE), L"%d * %d Core(s)", CpuNum, SmbiosType4Record->CoreCount);

  //
  // Update cache information via smbios.
  //
  gSmbiosType = EFI_SMBIOS_TYPE_CACHE_INFORMATION;

  Status = gSmbiosProtocol->GetNext (gSmbiosProtocol, &gSmbiosHandle, &gSmbiosType, &SmbiosRecord, NULL);
  if (EFI_ERROR(Status)) {
    DEBUG((EFI_D_ERROR, "UpdateCacheInformation SmbiosProtocol GetNext fail Status=%r\n", Status));
    goto EndGetSmbiosInfo;
  }

  while (!EFI_ERROR(Status)) {
    SmbiosType7Record = (SMBIOS_TABLE_TYPE7 *) SmbiosRecord;

    //DEBUG((EFI_D_ERROR, " Get CacheConfiguration=0x%x\n", SmbiosType7Record->CacheConfiguration));
    //DEBUG((EFI_D_ERROR, " Get MaximumCacheSize=0x%x\n", SmbiosType7Record->MaximumCacheSize));

    if (SmbiosType7Record->MaximumCacheSize != 0) {
      CacheLevel = SmbiosType7Record->CacheConfiguration >> SMBIOS_CACHE_LEVEL_OFFSET & SMBIOS_CACHE_LEVEL_MASK;
      CacheSizeGranularity = SmbiosType7Record->MaximumCacheSize >> SMBIOS_CACHE_SIZE_GRANULARITY_OFFSET & SMBIOS_CACHE_SIZE_GRANULARITY_MASK;
      CacheSizeGranularity = CacheSizeGranularity ? SMBIOS_CACHE_SIZE_GRANULARITY_64K : SMBIOS_CACHE_SIZE_GRANULARITY_1K;
      CacheSize = SmbiosType7Record->MaximumCacheSize >> SMBIOS_CACHE_SIZE_OFFSET & SMBIOS_CACHE_SIZE_MASK;
      CacheSize *= CacheSizeGranularity;

//add-klk-lyang-P000A-start//
      if (CacheSize > (1024*1024)) {
        UintIndex = 2;
        CacheSize = CacheSize/1024/1024;
      } else if (CacheSize > 1024) {
        UintIndex = 1;
        CacheSize = CacheSize/1024;
      } else {
        UintIndex = 0;
      }
//add-klk-lyang-P000A-end//
      switch (CacheLevel) {
        case 0: {//CACHE_LEVEL_1
          InitString (gAdvHiiHandle, STRING_TOKEN (STR_BOARD_PROCESSOR_L1CACHE_VALUE), L"%d %s", CacheSize,CacheSizeUnit[UintIndex]);
          break;
        }
        case 1: {//CACHE_LEVEL_2
          InitString (gAdvHiiHandle, STRING_TOKEN (STR_BOARD_PROCESSOR_L2CACHE_VALUE), L"%d %s", CacheSize,CacheSizeUnit[UintIndex]);
          break;
        }
        case 2: {//CACHE_LEVEL_3
          InitString (gAdvHiiHandle, STRING_TOKEN (STR_BOARD_PROCESSOR_L3CACHE_VALUE), L"%d %s", CacheSize,CacheSizeUnit[UintIndex]);
          break;
        }
        case 3: //CACHE_LEVEL_4
        case 4: //CACHE_LEVEL_5
        case 5: //CACHE_LEVEL_6
        case 6: //CACHE_LEVEL_7
        case 7: //CACHE_LEVEL_8
        default:
          break;
      }
    }

    Status = gSmbiosProtocol->GetNext (gSmbiosProtocol, &gSmbiosHandle, &gSmbiosType, &SmbiosRecord, NULL);
  }

EndGetSmbiosInfo:
  return;
}

